/* Copyright 2021 Kerim Yalcin
**
**   Licensed under the Apache License, Version 2.0 (the "License");
**   you may not use this file except in compliance with the License.
**   You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
**   Unless required by applicable law or agreed to in writing, software
**   distributed under the License is distributed on an "AS IS" BASIS,
**   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
**   See the License for the specific language governing permissions and
**   limitations under the License.
*/

#include "WindowFrame.hpp"

/***** private *****/

LRESULT CALLBACK Agx::WindowFrame::WindowProcedure_toWNDCLASSEXA(HWND pHwnd, UINT pMsg, WPARAM pWParam, LPARAM pLParam) {
    WindowFrame* frame =
        (WindowFrame*) GetWindowLongPtrA(pHwnd, GWLP_USERDATA);
    if (frame) return frame->Window_Procedure(pHwnd, pMsg, pWParam, pLParam);
    return DefWindowProc(pHwnd, pMsg, pWParam, pLParam);
}

void Agx::WindowFrame::print_Win32_Error(const std::string& pDescription) {
    std::cout << "Error: " << pDescription <<
        ": " << GetLastError() << std::endl;
}

/***** protected *****/

void Agx::WindowFrame::set_WndClass_Name(const std::string& pWndClassName) {
    mWndClass_Name = pWndClassName;
}

const std::string& Agx::WindowFrame::get_WndClass_Name() {
    return mWndClass_Name;
}

void Agx::WindowFrame::set_WndClass_Instance(HINSTANCE pWndClass_Instance) {
    mWndClass_Instance = pWndClass_Instance;
}

HINSTANCE Agx::WindowFrame::get_WndClass_Instance() {
    return mWndClass_Instance;
}

void Agx::WindowFrame::set_WndClass_Background(HBRUSH pWndClass_Background) {
    mWndClass_Background = pWndClass_Background;
}

HBRUSH Agx::WindowFrame::get_WndClass_Background() {
    return mWndClass_Background;
}

void Agx::WindowFrame::register_WndClass() {
    mWndClass.cbSize            = sizeof(WNDCLASSEXA);
    mWndClass.lpszClassName     = mWndClass_Name.c_str();
    mWndClass.hInstance         = mWndClass_Instance;
    mWndClass.lpfnWndProc       = WindowProcedure_toWNDCLASSEXA;
    mWndClass.hbrBackground     = mWndClass_Background;

    if(!RegisterClassExA(&mWndClass))
        print_Win32_Error("Agx::WindowFrame::register_WndClass");
}

void Agx::WindowFrame::add_toWindowBase_Set(WindowBase* pWindowBase) {
    pWindowBase->create((LONG_PTR)this);

    if (pWindowBase->is_linked_withFrame()) {
        mWindowBase_Set.push_back(pWindowBase);
    }
}

void Agx::WindowFrame::free_WindowBase_Set() {
    for(int i = 0; i < mWindowBase_Set.size(); ++i) {
        delete mWindowBase_Set[i];
        mWindowBase_Set[i] = nullptr;
    }
}

//***** public ******

Agx::WindowFrame::WindowFrame() {
    mWndClass = {};
}

LRESULT CALLBACK Agx::WindowFrame::Window_Procedure(HWND pHwnd, UINT pMsg, WPARAM pWParam, LPARAM pLParam) {
    switch (pMsg) {
        case WM_CREATE:     Window_Procedure_Create(pHwnd, pMsg, pWParam, pLParam); break;
        case WM_CLOSE:      Window_Procedure_Close(pHwnd, pMsg, pWParam, pLParam); break;
        case WM_DESTROY:    Window_Procedure_Destroy(pHwnd, pMsg, pWParam, pLParam); break;
        case WM_COMMAND:    Window_Procedure_Command(pHwnd, pMsg, pWParam, pLParam); break;
        case WM_NOTIFY:     Window_Procedure_Notify(pHwnd, pMsg, pWParam, pLParam); break;
        default:            
            return DefWindowProcA(pHwnd, pMsg, pWParam, pLParam);
    }
    return DefWindowProcA(pHwnd, pMsg, pWParam, pLParam);
}

int Agx::WindowFrame::run(HINSTANCE pInstance, HINSTANCE pPreviousInstance, PSTR pCmdLine, INT pCmdShow) {
    return 0;
}